package org.phalanx.map.xml;

import java.util.ArrayList;
import java.util.Collections;

import org.phalanx.map.MapCoordinates;
import org.phalanx.map.MapTile;
import org.phalanx.map.MapTileSet;
import org.phalanx.map.PhalanxMap;
import org.phalanx.map.PhalanxMapTerrain;
import org.phalanx.xml.XMLObject;

public class PhalanxMapXMLWriter {
	private PhalanxMap mapper;
	private boolean isDefaultTileSet;
	private String createdBy;
	private ArrayList<XMLObject> xmlDataSet;
	
	public PhalanxMapXMLWriter(PhalanxMap m, boolean defaultTS, String createdBy){
		this.setMap(m);
		this.setDefaultTileSet(defaultTS);
		this.setCreatedBy(createdBy);
	}

	public PhalanxMap getMap() {
		return mapper;
	}

	public void setMap(PhalanxMap mapper) {
		this.mapper = mapper;
	}

	public boolean isDefaultTileSet() {
		return isDefaultTileSet;
	}

	public void setDefaultTileSet(boolean isDefaultTileSet) {
		this.isDefaultTileSet = isDefaultTileSet;
	}

	public String getCreatedBy() {
		return createdBy;
	}

	public void setCreatedBy(String createdBy) {
		this.createdBy = createdBy;
	}
	
	
	public String writeOutXML(){
		String xmlData = "";
		setXMLObjects();
		
		xmlData = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
		xmlData += getXMLString();
		
		
		/*
		buffer.append(getXMLVersionEncoding());
		buffer.append(startPhalanxMap());
		buffer.append(writeIndentationLevel(1));*/
		
		return xmlData;
	}
	
	private String getXMLString(){
		String data = "";
		
		for (int i = 0; i < xmlDataSet.size(); i++){
			XMLObject o = xmlDataSet.get(i);
			
			if (o.getParentTag() == null){
				data = getChildData(o,xmlDataSet, 0);
				break;
			}
		}
		
		return data;
	}
	
	private String getChildData(XMLObject xmlTag, ArrayList<XMLObject> tagList, int level){
		StringBuffer data = xmlTag.getParentTag() != null ? new StringBuffer(writeIndentationLevel(level)) : new StringBuffer("");
		
		ArrayList<XMLObject> childTagList = new ArrayList<XMLObject>();
		
		data.append("<" + xmlTag.getXmlTag());
		
		ArrayList<String> attr = xmlTag.getAttributesList();
		
		for (int i = 0; i < attr.size(); i++){
			String attrName = attr.get(i);
			data.append(" " + attrName + "=\"" + xmlTag.getAttributes(attrName) + "\"");
		}
		
		for (int i = 0; i < tagList.size(); i++){
			XMLObject o = tagList.get(i);
			
			if (o.getParentTag() != null && o.getParentTag().equals(xmlTag.getXmlTag())){
				childTagList.add(o);
			}
		}
		
		if (!childTagList.isEmpty()){
			level++;
			data.append(">" + xmlTag.getStoredData()); 
			
			Collections.sort(childTagList);

			for (int i = 0; i < childTagList.size(); i++){
				XMLObject o = childTagList.get(i);
				data.append("\n" + getChildData(o, tagList, level));
			}
			level--;
			data.append("\n" + writeIndentationLevel(level) + "</" + xmlTag.getXmlTag() + ">");
		}else if (xmlTag.getStoredData() != null && xmlTag.getStoredData().length() > 0){
			data.append(">" + xmlTag.getStoredData() + "</" + xmlTag.getXmlTag() + ">");
		}
		else {
			data.append("/>");
		}
		return data.toString();
	}
	
	private void setXMLObjects(){
		xmlDataSet = new ArrayList<XMLObject>();
		XMLObject tempSet = new XMLObject();
		tempSet.setParentTag(null);
		tempSet.setXmlTag("PhalanxMap");
		tempSet.setAttribute("name", mapper.getMapName());
		tempSet.setAttribute("version", mapper.getMapVersion());
		
		xmlDataSet.add(tempSet);
		
		tempSet = new XMLObject();
		tempSet.setParentTag("PhalanxMap");
		tempSet.setXmlTag("MetaData");
		tempSet.setWeight(100);
		
		xmlDataSet.add(tempSet);
		
		tempSet = new XMLObject();
		tempSet.setParentTag("MetaData");
		tempSet.setXmlTag("Author");
		tempSet.setStoredData(mapper.getAuthorName() != null ? mapper.getAuthorName() : "");
		tempSet.setWeight(10);
		
		xmlDataSet.add(tempSet);

		tempSet = new XMLObject();
		tempSet.setParentTag("MetaData");
		tempSet.setXmlTag("Email");
		tempSet.setStoredData(mapper.getAuthorEmail() != null ? mapper.getAuthorEmail() : "");
		tempSet.setWeight(9);
		
		xmlDataSet.add(tempSet);
		
		tempSet = new XMLObject();
		tempSet.setParentTag("MetaData");
		tempSet.setXmlTag("Country");
		tempSet.setStoredData(mapper.getAuthorCountry() != null ? mapper.getAuthorCountry() : "");
		tempSet.setWeight(8);
		
		xmlDataSet.add(tempSet);
		
		tempSet = new XMLObject();
		tempSet.setParentTag("MetaData");
		tempSet.setXmlTag("AuthorURL");
		tempSet.setStoredData(mapper.getAuthorURL() != null ? mapper.getAuthorURL() : "");
		tempSet.setWeight(7);
		
		xmlDataSet.add(tempSet);
		
		tempSet = new XMLObject();
		tempSet.setParentTag("PhalanxMap");
		tempSet.setXmlTag("Created");
		tempSet.setStoredData(createdBy);
		tempSet.setWeight(99);
		
		xmlDataSet.add(tempSet);
		
		tempSet = new XMLObject();
		tempSet.setParentTag("PhalanxMap");
		tempSet.setXmlTag("ImportSet");
		tempSet.setAttribute("tileset", isDefaultTileSet ? "Default" : mapper.getMapTileSet().getCanonicalFilePath());
		tempSet.setWeight(98);
		
		xmlDataSet.add(tempSet);
		
		tempSet = new XMLObject();
		tempSet.setParentTag("PhalanxMap");
		tempSet.setXmlTag("Mapper");
		tempSet.setAttribute("defaulttile", mapper.getMapTileSet().getTerrainRefNameFromTile(mapper.getDefaultTile()));
		tempSet.setAttribute("width", mapper.getMapWidth().toString());
		tempSet.setAttribute("length", mapper.getMapLength().toString());
		tempSet.setAttribute("TileSize", mapper.getTileSize().toString());
		tempSet.setWeight(98);
		
		xmlDataSet.add(tempSet);
		
		int mapW = mapper.getMapWidth();
		int mapL = mapper.getMapLength();
		String defaultTileSet = mapper.getMapTileSet().getTerrainRefNameFromTile(mapper.getDefaultTile());
		
		for (int i = 0; i < mapW; i++){
			for (int j = 0; j < mapL; j++){
				MapTile newTile = mapper.getMapTileAt(i, j);
				String tileName = mapper.getMapTileSet().getTerrainRefNameFromTile(newTile);
				
				if (!tileName.equals(defaultTileSet)){
					tempSet = new XMLObject();
					tempSet.setParentTag("Mapper");
					tempSet.setXmlTag("Square");
					tempSet.setAttribute("xvalue", i + "");
					tempSet.setAttribute("yvalue", j + "");
					tempSet.setAttribute("tile", tileName);
					
					xmlDataSet.add(tempSet);
				}
			}
		}
		
		// Build Points
		
		if (!mapper.getIsBuildPointsEmpty()){
			ArrayList<MapCoordinates> buildPointsList = mapper.getBuildPoints();
			
			for (int i = 0; i < buildPointsList.size(); i++){
				tempSet = new XMLObject();
				tempSet.setParentTag("Mapper");
				tempSet.setXmlTag("BuildPoint");
				tempSet.setAttribute("xvalue", buildPointsList.get(i).getX().toString());
				tempSet.setAttribute("yvalue", buildPointsList.get(i).getY().toString());
				
				xmlDataSet.add(tempSet);
			}
		}
		
	}
	
	private String writeIndentationLevel(Integer level){
		String indentationString = "";
		
		for (int i = 0; i < level; i++){
			indentationString += "\t";
		}
		
		return indentationString;
	}
	
	private String getAttributeString(String key, String value){
		return key + "=" + "\"" + value + "\"";
	}
}
